package com.pjc.db;

import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.MongoException;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import java.net.UnknownHostException;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * mongoDB操作类
 * 
 * @author 王畅
 * @since 2015年6月21日
 */
public class MongoDB {
	protected static final Logger log = LoggerFactory.getLogger(MongoDB.class);
	private static MongoItem mongoItem;

	/**
	 * 无密码认证
	 * 
	 * @author 王畅
	 * @param host
	 * @param port
	 * @throws Exception
	 */
	public static void init(String host, int port) throws Exception {
		synchronized (MongoDB.class) {
			if (mongoItem == null) {
				log.debug("初始化mongo连接  HOST=" + host + "  PORT=" + port);
				mongoItem = new MongoItem(host, port);
			}
		}
	}

	/**
	 * 密码认证
	 * 
	 * @author 王畅
	 * @param host
	 * @param port
	 * @param dbName
	 * @param uid
	 * @param pwd
	 * @throws Exception
	 */
	public static void init(String host, int port, String dbName, String uid, String pwd) throws Exception {
		synchronized (MongoDB.class) {
			if (mongoItem == null) {
				log.debug("初始化mongo连接  HOST=" + host + "  PORT=" + port + " DB=" + dbName + " UID=" + uid + " PWD=" + pwd);
				mongoItem = new MongoItem(host, port, dbName, uid, pwd);
			}
		}
	}

	public static DB getDB(String dbName) throws Exception {
		if (mongoItem == null) {
			throw new Exception("Mongodb is not inited.");
		}
		return mongoItem.mongo.getDB(dbName);
	}

	public static void close() throws Exception {
		if (mongoItem == null)
			return;
		mongoItem.mongo.close();
	}

	private static class MongoItem {

		private MongoClient mongo;
		private String host;
		private int port;
		private String uid;
		private String pwd;
		private String dbName;

		public MongoItem(String host, int port) throws UnknownHostException, MongoException {
			this.host = host;
			this.port = port;
			init(false);
		}

		public MongoItem(String host, int port, String dbName, String uid, String pwd) throws UnknownHostException, MongoException {
			this.host = host;
			this.port = port;
			this.uid = uid;
			this.pwd = pwd;
			this.dbName = dbName;
			init(true);
		}

		public void init(boolean auth) throws UnknownHostException, MongoException {
			MongoDB.log.debug("Conn MongoDB on " + this.host + "[" + this.port + "]");
			MongoClientOptions.Builder build = new MongoClientOptions.Builder();
			build.socketKeepAlive(true);
			build.connectionsPerHost(100); // 与目标数据库能够建立的最大connection数量为100
			build.threadsAllowedToBlockForConnectionMultiplier(15); // 如果当前所有的connection都在使用中，则每个connection上可以有50个线程排队等待
			build.connectTimeout(15000); // 与数据库建立连接的timeout设置为1分钟
			build.socketTimeout(30000);
			ServerAddress serverAddress = new ServerAddress(this.host, this.port);
			if (!auth) {
				this.mongo = new MongoClient(serverAddress, build.build());
			} else {
				this.mongo = new MongoClient(serverAddress, Arrays.asList(MongoCredential.createMongoCRCredential(this.uid, this.dbName, this.pwd.toCharArray())), build.build());
			}
			this.mongo.setWriteConcern(WriteConcern.SAFE);
		}
	}
}
